package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/kokardy/listing"
	"github.com/spf13/pflag"
)

var basic_button_properties = []string{
	"BS_3STATE",
	"BS_AUTO3STATE",
	"BS_AUTOCHECKBOX",
	"BS_AUTORADIOBUTTON",
	"BS_BITMAP",
	"BS_BOTTOM",
	"BS_CENTER",
	"BS_CHECKBOX",
	"BS_COMMANDLINK",
	"BS_DEFCOMMANDLINK",
	"BS_DEFPUSHBUTTON",
	"BS_DEFSPLITBUTTON",
	//BS_GROUPBOX
	"BS_ICON",
	"BS_FLAT",
	"BS_LEFT",
	"BS_LEFTTEXT",
	"BS_MULTILINE",
	//"BS_NOTIFY",
	//"BS_OWNERDRAW",
	"BS_PUSHBUTTON",
	"BS_PUSHLIKE",
	"BS_RADIOBUTTON",
	"BS_RIGHT",
	"BS_RIGHTBUTTON",
	"BS_SPLITBUTTON",
	"BS_TEXT",
	"BS_TOP",
	"BS_TYPEMASK",
	"BS_USERBUTTON",
	"BS_VCENTER",
}

var windows_properties = []string{
	"WS_BORDER",
	"WS_CAPTION",
	"WS_CHILD",
	"WS_CHILDWINDOW",
	"WS_CLIPCHILDREN",
	"WS_CLIPSIBLINGS",
	"WS_DISABLED",
	"WS_DLGFRAME",
	"WS_GROUP",
	"WS_HSCROLL",
	"WS_ICONIC",
	"WS_MAXIMIZE",
	"WS_MAXIMIZEBOX",
	"WS_MINIMIZE",
	"WS_MINIMIZEBOX",
	"WS_OVERLAPPED",
	"WS_OVERLAPPEDWINDOW",
	"WS_POPUP",
	"WS_POPUPWINDOW",
	"WS_SIZEBOX",
	"WS_SYSMENU",
	"WS_TABSTOP",
	"WS_THICKFRAME",
	"WS_TILED",
	"WS_TILEDWINDOW",
	"WS_VISIBLE",
	"WS_VSCROLL",
}

var clear_cmd_pre = `
rm *.exe
rm *.obj
rm *.manifest
sleep 3
`

const property_num = 27

func main() {
	rand.Seed(time.Now().Unix())
	var windows_properties_num = "0"
	var properties_group_num = 1
	var target_dir = "./"

	pflag.StringVar(&windows_properties_num, "windows-properties-num", windows_properties_num, "windows-properties-num,value 0-27")
	pflag.IntVar(&properties_group_num, "properties-group-num", properties_group_num, "max properties-group-num")
	pflag.StringVar(&target_dir, "target-dir", target_dir, "target dir")

	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()

	build_command := ""
	build_file_path := fmt.Sprintf("%s/run_build_exe.sh", target_dir)
	nums := strings.Split(windows_properties_num, ",")
	for _, numStr := range nums {
		num, err := strconv.Atoi(numStr)
		if err != nil {
			fmt.Printf("%v", err)
		}
		cmd := generateOnece(num, properties_group_num, target_dir)
		if len(cmd) > 0 {
			build_command = fmt.Sprintf("%s\n%s", build_command, cmd)
		}
	}
	ioutil.WriteFile(build_file_path, []byte(build_command), os.ModePerm)

}

func generateOnece(windows_properties_num int, properties_group_num int, target_dir string) string {
	if windows_properties_num > 27 || windows_properties_num < 0 {
		fmt.Println("windows_properties_num error")
		return ""
	}

	if properties_group_num < 1 && properties_group_num > mathZuhe(property_num, windows_properties_num) {
		fmt.Println("properties_group_num error")
		return ""
	}

	count := 1
	build_command := fmt.Sprintf("%s\n", "mkdir targetDir")

	for each := range listing.Combinations(listing.StringReplacer(windows_properties), windows_properties_num, false, 5) {
		//print(each)
		if count > properties_group_num {
			break
		}
		pro_str := ""
		for _, each_basic := range basic_button_properties {
			str := each_basic
			for _, each_windows_property := range each.(listing.StringReplacer) {
				str = fmt.Sprintf("%s|%s", str, each_windows_property)
			}
			str = fmt.Sprintf("%s,\t\"%s\",\n", str, str)
			pro_str = fmt.Sprintf("%s%s", pro_str, str)
		}
		cpp_file := fmt.Sprintf("%s/button_exe_%03d_%010d.cpp", target_dir, windows_properties_num, count)
		code_str := fmt.Sprintf("%s%s%s", tmp_beg, pro_str, tmp_end)
		ioutil.WriteFile(cpp_file, []byte(code_str), os.ModePerm)

		build_command = fmt.Sprintf("%s%s\n", build_command, clear_cmd_pre)
		build_command = fmt.Sprintf("%scl -EHsc ./button_exe_%03d_%010d.cpp\n", build_command, windows_properties_num, count)
		build_command = fmt.Sprintf("%s%s\n", build_command, fmt.Sprintf("mv button_exe_%03d_%010d.exe targetDir", windows_properties_num, count))
		count++
	}
	build_command = fmt.Sprintf("%s%s\n", build_command, clear_cmd_pre)
	//fmt.Printf("%s",build_command)
	return build_command
}

//数学方法计算排列数(从n中取m个数)
func mathPailie(n int, m int) int {
	return jieCheng(n) / jieCheng(n-m)
}

//数学方法计算组合数(从n中取m个数)
func mathZuhe(n int, m int) int {
	return jieCheng(n) / (jieCheng(n-m) * jieCheng(m))
}

//阶乘
func jieCheng(n int) int {
	result := 1
	for i := 2; i <= n; i++ {
		result *= i
	}
	return result
}
